/////////////////////////////////////////////////////////////////////////////
// Name:        ax_property.cpp
// Purpose:     Property classes
// Author:      Julian Smart
// Modified by:
// Created:     2009-02-14
// RCS-ID:      $Id$
// Copyright:   (c) Julian Smart
// Licence:     New BSD License
/////////////////////////////////////////////////////////////////////////////

#include "wx/wx.h"

#include "ax/ax_property.h"

IMPLEMENT_CLASS(AxProperty, wxObject)

wxString AxPropertyCategory::sm_category;

IMPLEMENT_CLASS(AxProperties, wxObject)

AxProperty* AxProperties::AddProperty(AxProperty* property, const wxString& insertAfter)
{
    AxProperty* oldProp = FindProperty(property->GetName());
    if (oldProp)
        m_list.DeleteObject(oldProp);

    wxObjectList::compatibility_iterator insertBeforeNode = NULL;
    if (!insertAfter.IsEmpty())
    {
        AxProperty* insertAfterProp = FindProperty(insertAfter);
        if (insertAfterProp)
        {
            wxObjectList::compatibility_iterator node = m_list.Member(insertAfterProp);
            if (node)
                insertBeforeNode = node->GetNext();
        }
    }
    if (insertBeforeNode)
        m_list.Insert(insertBeforeNode, property);
    else
        m_list.Append(property);

    if (oldProp)
    {
        property->GetVariant() = oldProp->GetVariant();

        delete oldProp;
    }
    return property;
}

void AxProperties::RemoveProperty(AxProperty* property)
{
    m_list.DeleteObject(property);
}

void AxProperties::DeleteProperty(AxProperty* property)
{
    m_list.DeleteObject(property);
    delete property;
}

void AxProperties::DeleteProperty(size_t i)
{
    AxProperty* prop = GetProperty(i);
    if (prop)
        DeleteProperty(prop);
}

void AxProperties::DeleteProperty(const wxString& name)
{
    AxProperty* prop = FindProperty(name);
    if (prop)
    {
        m_list.DeleteObject(prop);
        delete prop;
    }
}

AxProperty* AxProperties::FindProperty(const wxString& name) const
{
    wxObjectList::compatibility_iterator node = m_list.GetFirst();
    while (node)
    {
        AxProperty* prop = (AxProperty*) node->GetData();
        if (prop->GetName() == name)
            return prop;

        node = node->GetNext();
    }
    return (AxProperty*) NULL;
}

AxProperty* AxProperties::FindPropertyByDisplayName(const wxString& name)
{
    wxObjectList::compatibility_iterator node = m_list.GetFirst();
    while (node)
    {
        AxProperty* prop = (AxProperty*) node->GetData();
        if (prop->GetDisplayName() == name)
            return prop;

        node = node->GetNext();
    }
    return (AxProperty*) NULL;
}

wxVariant AxProperties::FindPropertyValue(const wxString& name) const
{
    AxProperty* prop = FindProperty(name);
    if (prop)
        return prop->m_variant;
    else
        return wxEmptyString;
}

wxString AxProperties::FindPropertyValueString(const wxString& name) const
{
    AxProperty* prop = FindProperty(name);
    if (prop)
        return prop->m_variant.GetString();
    else
        return wxEmptyString;
}

bool AxProperties::FindPropertyValueBool(const wxString& name) const
{
    AxProperty* prop = FindProperty(name);
    if (prop)
        return prop->m_variant.GetBool();
    else
        return false;
}

long AxProperties::FindPropertyValueLong(const wxString& name) const
{
    AxProperty* prop = FindProperty(name);
    if (prop)
        return prop->m_variant.GetLong();
    else
        return 0;
}

double AxProperties::FindPropertyValueDouble(const wxString& name) const
{
    AxProperty* prop = FindProperty(name);
    if (prop)
        return prop->m_variant.GetDouble();
    else
        return 0.0;
}

AxProperty* AxProperties::FindOrCreateProperty(const wxString& name)
{
    AxProperty* prop = FindProperty(name);
    if (!prop)
    {
        prop = new AxProperty(name);
        AddProperty(prop);
    }
    return prop;
}

void AxProperties::Clear()
{
    m_list.DeleteContents(TRUE);
    m_list.Clear();
    m_list.DeleteContents(FALSE);
}

void AxProperties::Copy(const AxProperties& properties)
{
    wxObjectList::compatibility_iterator node = properties.m_list.GetFirst();
    while (node)
    {
        AxProperty* prop = (AxProperty*) node->GetData();

        AddProperty(new AxProperty(* prop));

        node = node->GetNext();
    }
}

bool AxProperties::operator == (const AxProperties& properties)
{
    if (m_list.GetCount() != properties.m_list.GetCount())
        return false;

    wxObjectList::compatibility_iterator node1 = m_list.GetFirst();
    wxObjectList::compatibility_iterator node2 = properties.m_list.GetFirst();
    while (node1 && node2)
    {
        AxProperty* prop1 = (AxProperty*) node1->GetData();
        AxProperty* prop2 = (AxProperty*) node2->GetData();

        if (!(*prop1 == *prop2))
            return false;

        node1 = node1->GetNext();
        node2 = node2->GetNext();
    }
    return true;
}

void AxProperties::SetProperty(const AxProperty& prop)
{
    AxProperty* p = FindOrCreateProperty(prop.GetName());
    (*p) = prop;
}

void AxProperties::SetProperty(const wxString& name, const wxString& value)
{
    AxProperty* prop = FindOrCreateProperty(name);
    prop->SetValue(value);
}

void AxProperties::SetProperty(const wxString& name, long value)
{
    AxProperty* prop = FindOrCreateProperty(name);
    prop->GetVariant() = value;
}

void AxProperties::SetProperty(const wxString& name, double value)
{
    AxProperty* prop = FindOrCreateProperty(name);
    prop->GetVariant() = value;
}

void AxProperties::SetProperty(const wxString& name, bool value)
{
    AxProperty* prop = FindOrCreateProperty(name);
    prop->GetVariant() = (bool) value;
}

void AxProperties::SetProperty(const wxString& name, const wxVariant& value)
{
    AxProperty* prop = FindOrCreateProperty(name);
    prop->SetValue(value);
}

AxProperty* AxProperties::GetNth(int i) const
{
    wxASSERT( i < (int) GetCount() );
    if (i < (int) GetCount())
    {
        wxObjectList::compatibility_iterator node = m_list.Item(i);
        return (AxProperty*) node->GetData();
    }
    return NULL;
}
